package wili.attrMapping._user.b1.exp;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import wili.c.Ca;
import wili.c.reg.MatchRet;
import wili.c.reg.OneMatch;

/**
 * 
 * @author weila 2022年10月5日
 */
public class Funb1 extends MathExpB1 {
	public List<MathExpB1> args;

	public MathExpB1 arg;

	public String type;

	public String name;

	public String toString() {
		if (this.expSt != null)
			return this.expSt;
		return this.getString(1);
	}

	public Funb1(MatchRet mat) {
		String st = mat.son(0).getString(1);
		int ind = 0;
		if (st.charAt(0) == '!') {
			ind = 1;
			this.isNot = true;
		}
		if (st.startsWith("[", ind)) {
			List<OneMatch> lis = mat.son(1).toTimesMatch().list;
			args = new ArrayList<>(lis.size());
			for (int i = 0; i < lis.size(); i++) {
				args.add(MathExpB1.expOf(lis.get(i)));
			}
			this.name = mat.son(-4).getString(1);
			arg = MathExpB1.expOf(mat.son(-2));
		} else {
			Ca.asert(false, st);
		}
	}

	private Funb1(List<MathExpB1> args, MathExpB1 arg) {
		super();
		this.args = args;
		this.arg = arg;
		this.name = "includes";
	}

	public void traverse(Predicate<MathExpB1> pred) {
		pred.test(this);
		for (MathExpB1 arg : args) {
			arg.traverse(pred);
		}
		arg.traverse(pred);
	}

	@Override
	public Boolean isTrue() {
		return (Boolean) value();
	}

	@Override
	public <T> T value() {
		// TODO Auto-generated method stub
		return null;
	}

	public static Funb1 newInst_includesFun(List<MathExpB1> eqList) {
		Ca.asert(eqList.size() >= 2, "");
		List<MathExpB1> valueArgs = new ArrayList<>(eqList.size());
		MathExpB1 varArg = null;
		for (MathExpB1 ele : eqList) {
			if (ele.ll instanceof Valueb1) {
				valueArgs.add(ele.ll);
				if (varArg == null) {
					varArg = ele.rr;
				} else {
					Ca.asert(varArg.equals(ele.rr), "");
				}
			} else if (ele.ll instanceof Varb1) {
				valueArgs.add(ele.rr);
				if (varArg == null) {
					varArg = ele.ll;
				} else {
					Ca.asert(varArg.equals(ele.ll), "");
				}
			} else {
				Ca.asert(false, ele);
			}
		}
		return new Funb1(valueArgs, varArg);
	}

	@Override
	public String getString(int refresh) {
		Ca.pause();
		if (refresh == 1 || expSt == null) {
			String st = args.stream().map(a -> a.getString(refresh)).collect(Collectors.joining(","));
			return this.expSt = "[" + st + "]." + name + "(" + arg.getString(refresh) + ")";
		}
		return this.expSt;
	}

	public boolean equals(Object o) {
		if (o instanceof Funb1) {
			Funb1 obj = (Funb1) o;
			if (!this.name.equals(obj.name))
				return false;
			if (!this.arg.equals(obj.arg))
				return false;
			if (!MathExpB1.isEqualsList(args, obj.args))
				return false;
			return true;
		}
		return false;
	}
}
